module defl.c.ecore.data;

extern (C):
   
const int ECORE_SORT_MIN = 0;
const int ECORE_SORT_MAX = 1;

alias void function(void* value, void* user_data) Ecore_For_Each;
alias void function(void* data) Ecore_Free_Cb;
alias uint function(void* key) Ecore_Hash_Cb;
alias int function(void* data1, void* data2) Ecore_Compare_Cb;

struct Ecore_Strbuf;

struct Ecore_List_Node {
  void* data;
  Ecore_List_Node* next;
}

struct Ecore_List {
  Ecore_List_Node* first;	/* The first node in the list */
  Ecore_List_Node* last;	/* The last node in the list */
  Ecore_List_Node* current;	/* The current node in the list */
  
  Ecore_Free_Cb free_func;  /* The callback to free data in nodes */
  
  int nodes;		/* The number of nodes in the list */
  int index;		/* The position from the front of the
			 list of current node */
}

int ecore_direct_compare(void* key1, void* key2);
int ecore_str_compare(void* key1, void* key2);

uint ecore_direct_hash(void* key);
uint ecore_str_hash(void* key);

/* Creating and initializing new list structures */
Ecore_List* ecore_list_new();
int ecore_list_init(Ecore_List* list);

/* Adding items to the list */
int ecore_list_append(Ecore_List* list, void* _data);
int ecore_list_prepend(Ecore_List* list, void* _data);
int ecore_list_insert(Ecore_List* list, void* _data);
int ecore_list_append_list(Ecore_List* list, Ecore_List* append);
int ecore_list_prepend_list(Ecore_List* list, Ecore_List* prepend);

/* Removing items from the list */
int ecore_list_remove_destroy(Ecore_List* list);
void* ecore_list_remove(Ecore_List* list);
void* ecore_list_first_remove(Ecore_List* list);
void* ecore_list_last_remove(Ecore_List* list);

/* Retrieve the current position in the list */
void* ecore_list_current(Ecore_List* list);
void* ecore_list_first(Ecore_List* list);
void* ecore_list_last(Ecore_List* list);
int ecore_list_index(Ecore_List* list);
int ecore_list_count(Ecore_List* list);

/* Traversing the list */
int ecore_list_for_each(Ecore_List* list, Ecore_For_Each foreach_,
			void* user_data);
void* ecore_list_first_goto(Ecore_List* list);
void* ecore_list_last_goto(Ecore_List* list);
void* ecore_list_index_goto(Ecore_List* list, int index);
void* ecore_list_goto(Ecore_List* list, void* _data);

/* Traversing the list and returning data */
void* ecore_list_next(Ecore_List* list);
void* ecore_list_find(Ecore_List* list, Ecore_Compare_Cb compare,
	void* user_data);

/* Sorting the list */
int ecore_list_sort(Ecore_List* list, Ecore_Compare_Cb compare,
							  char order);
int ecore_list_mergesort(Ecore_List* list, Ecore_Compare_Cb compare,
							  char order);
int ecore_list_heapsort(Ecore_List* list, Ecore_Compare_Cb compare,
							  char order);
void ecore_list_merge(Ecore_List* list, Ecore_List *l2, 
							  Ecore_Compare_Cb, char order);

/* Check to see if there is any data in the list */
int ecore_list_empty_is(Ecore_List* list);

/* Remove every node in the list without freeing the list itself */
int ecore_list_clear(Ecore_List* list);
/* Free the list and it's contents */
void ecore_list_destroy(Ecore_List* list);

/* Creating and initializing list nodes */
Ecore_List_Node *ecore_list_node_new();
int ecore_list_node_init(Ecore_List_Node *newNode);

/* Destroying nodes */
int ecore_list_node_destroy(Ecore_List_Node * _e_node, Ecore_Free_Cb free_func);

int ecore_list_free_cb_set(Ecore_List* list, Ecore_Free_Cb free_func);

alias Ecore_List Ecore_DList;

struct Ecore_DList_Node {
  Ecore_List_Node single;
  Ecore_DList_Node* previous;
}

/* Creating and initializing new list structures */
Ecore_DList* ecore_dlist_new();
int ecore_dlist_init(Ecore_DList *list);
void ecore_dlist_destroy(Ecore_DList *list);

/* Adding items to the list */
int ecore_dlist_append(Ecore_DList* _e_dlist, void* _data);
int ecore_dlist_prepend(Ecore_DList* _e_dlist, void* _data);
int ecore_dlist_insert(Ecore_DList* _e_dlist, void* _data);
int ecore_dlist_append_list(Ecore_DList* _e_dlist, Ecore_DList* append);
int ecore_dlist_prepend_list(Ecore_DList* _e_dlist, Ecore_DList* prepend);

/* Info about list's state */
alias ecore_list_first ecore_dlist_first;
alias ecore_list_last ecore_dlist_last;
void* ecore_dlist_current(Ecore_DList* list);
int ecore_dlist_index(Ecore_DList* list);
alias ecore_list_count ecore_dlist_count;

/* Removing items from the list */
void* ecore_dlist_remove(Ecore_DList* _e_dlist);
void* ecore_dlist_first_remove(Ecore_DList* _e_dlist);
int ecore_dlist_remove_destroy(Ecore_DList* list);
void* ecore_dlist_last_remove(Ecore_DList* _e_dlist);

/* Traversing the list */
alias ecore_list_for_each ecore_dlist_for_each;
void* ecore_dlist_first_goto(Ecore_DList* _e_dlist);
void* ecore_dlist_last_goto(Ecore_DList* _e_dlist);
void* ecore_dlist_index_goto(Ecore_DList* _e_dlist, int index);
void* ecore_dlist_goto(Ecore_DList* _e_dlist, void* _data);

/* Traversing the list and returning data */
void* ecore_dlist_next(Ecore_DList* list);
void* ecore_dlist_previous(Ecore_DList* list);

/* Sorting the list */
int ecore_dlist_sort(Ecore_DList* list, Ecore_Compare_Cb compare,
							  char order);
int ecore_dlist_mergesort(Ecore_DList* list, Ecore_Compare_Cb compare,
							  char order);
alias ecore_list_heapsort ecore_dlist_heapsort;
void ecore_dlist_merge(Ecore_DList* list, Ecore_DList* l2, 
							  Ecore_Compare_Cb, char order);

/* Check to see if there is any data in the list */
int ecore_dlist_empty_is(Ecore_DList* _e_dlist);

/* Remove every node in the list without free'ing it */
int ecore_dlist_clear(Ecore_DList* _e_dlist);

/* Creating and initializing list nodes */
int ecore_dlist_node_init(Ecore_DList_Node* node);
Ecore_DList_Node* ecore_dlist_node_new();

/* Destroying nodes */
int ecore_dlist_node_destroy(Ecore_DList_Node* node, Ecore_Free_Cb free_func);

int ecore_dlist_free_cb_set(Ecore_DList* dlist, Ecore_Free_Cb free_func);

/*
* Hash Table Implementation:
* 
* Traditional hash table implementation. I had tried a list of tables
* approach to save on the realloc's but it ended up being much slower than
* the traditional approach.
*/

struct Ecore_Hash_Node {
  Ecore_Hash_Node* next; /* Pointer to the next node in the bucket list */
  void* key;	     /* The key for the data node */
  void* value;	     /* The value associated with this node */
}

struct Ecore_Hash {
  Ecore_Hash_Node** buckets;
  int size;		/* An index into the table of primes to
		 determine size */
  int nodes;		/* The number of nodes currently in the hash */

  int index;    /* The current index into the bucket table */
  
  Ecore_Compare_Cb compare;	/* The function used to compare node values */
  Ecore_Hash_Cb hash_func;	/* The callback function to determine hash */
  
  Ecore_Free_Cb free_key;	/* The callback function to free key */
  Ecore_Free_Cb free_value;	/* The callback function to free value */
}

/* Create and initialize a hash */
Ecore_Hash* ecore_hash_new(Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare);
int ecore_hash_init(Ecore_Hash* hash, Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare);

/* Functions related to freeing the data in the hash table */
int ecore_hash_free_key_cb_set(Ecore_Hash* hash, Ecore_Free_Cb callback);
int ecore_hash_free_value_cb_set(Ecore_Hash* hash, Ecore_Free_Cb callback);
void ecore_hash_destroy(Ecore_Hash* hash);

int ecore_hash_count(Ecore_Hash* hash);
int ecore_hash_for_each_node(Ecore_Hash* hash, Ecore_For_Each for_each_func,
				 void* user_data);
Ecore_List *ecore_hash_keys(Ecore_Hash* hash);

/* Retrieve and store data into the hash */
void* ecore_hash_get(Ecore_Hash* hash, void* key);
int ecore_hash_set(Ecore_Hash* hash, void* key, void* value);
int ecore_hash_hash_set(Ecore_Hash* hash, Ecore_Hash *set);
void* ecore_hash_remove(Ecore_Hash* hash, void* key);
void* ecore_hash_find(Ecore_Hash* hash, Ecore_Compare_Cb compare, void* value);
void ecore_hash_dump_graph(Ecore_Hash* hash);
void ecore_hash_dump_stats(Ecore_Hash* hash);

struct Ecore_Path_Group
{
	Ecore_List *paths;
}

/*
* Create a new path group
*/
Ecore_Path_Group* ecore_path_group_new();

/*
* Destroy a previous path group
*/
void ecore_path_group_del(Ecore_Path_Group* group);

/*
* Add a directory to be searched for files
*/
void ecore_path_group_add(Ecore_Path_Group* group, char* path);

/*
* Remove a directory to be searched for files
*/
void ecore_path_group_remove(Ecore_Path_Group* group, char* path);

/*
* Find the absolute path if it exists in the group of paths
*/
char* ecore_path_group_find(Ecore_Path_Group* group, char* name);

/*
* Get a list of all the available files in a path set
*/
Ecore_List* ecore_path_group_available(Ecore_Path_Group* group);

struct Ecore_Plugin
{
	void* handle;
}

/*
* Load the specified plugin
*/
Ecore_Plugin* ecore_plugin_load(Ecore_Path_Group* group, char* plugin, char* version_);

/*
* Unload the specified plugin
*/
void ecore_plugin_unload(Ecore_Plugin* plugin);

/*
* Lookup the specified symbol for the plugin
*/
void* ecore_plugin_symbol_get(Ecore_Plugin* plugin, char* symbol_name);

Ecore_List* ecore_plugin_available_get(Ecore_Path_Group* group);

struct Ecore_Sheap {
  void** data;
  int size;
  int space;  
  char order, sorted;
  
  /* Callback for comparing node values, default is direct comparison */
  Ecore_Compare_Cb compare;

  /* Callback for freeing node data, default is NULL */
  Ecore_Free_Cb free_func;
}

Ecore_Sheap* ecore_sheap_new(Ecore_Compare_Cb compare, int size);
void ecore_sheap_destroy(Ecore_Sheap* heap);
int ecore_sheap_init(Ecore_Sheap* heap, Ecore_Compare_Cb compare, int size);
int ecore_sheap_free_cb_set(Ecore_Sheap *heap, Ecore_Free_Cb free_func);
int ecore_sheap_insert(Ecore_Sheap *heap, void* data);
void* ecore_sheap_extract(Ecore_Sheap *heap);
void* ecore_sheap_extreme(Ecore_Sheap *heap);
int ecore_sheap_change(Ecore_Sheap *heap, void* item, void* newval);
int ecore_sheap_compare_set(Ecore_Sheap *heap, Ecore_Compare_Cb compare);
void ecore_sheap_order_set(Ecore_Sheap *heap, char order);
void ecore_sheap_sort(Ecore_Sheap *heap);

void* ecore_sheap_item(Ecore_Sheap *heap, int i);

struct Ecore_String {
  char *string;
  int references;
}

int ecore_string_init();
void ecore_string_shutdown();
char* ecore_string_instance(char* string);
void ecore_string_release(char* string);
void ecore_string_hash_dump_graph();
void ecore_string_hash_dump_stats();

struct Ecore_Tree_Node {
  
  /* The actual data for each node */
  void* key;
  void* value;
  
  /* Pointers to surrounding nodes */
  Ecore_Tree_Node* parent;
  Ecore_Tree_Node* left_child;
  Ecore_Tree_Node* right_child;
  
  /* Book keeping information for quicker balancing of the tree */
  int max_right;
  int max_left;
}

struct Ecore_Tree {
  /* Nodes of the tree */
  Ecore_Tree_Node* tree;
  
  /* Callback for comparing node values, default is direct comparison */
  Ecore_Compare_Cb compare_func;
  
  /* Callback for freeing node data, default is NULL */
  Ecore_Free_Cb free_value;
  /* Callback for freeing node key, default is NULL */
  Ecore_Free_Cb free_key;
}

/* Some basic tree functions */
/* Allocate and initialize a new tree */
Ecore_Tree* ecore_tree_new(Ecore_Compare_Cb compare_func);
/* Initialize a new tree */
int ecore_tree_init(Ecore_Tree* tree, Ecore_Compare_Cb compare_func);

/* Free the tree */
int ecore_tree_destroy(Ecore_Tree* tree);
/* Check to see if the tree has any nodes in it */
int ecore_tree_empty_is(Ecore_Tree* tree);

/* Retrieve the value associated with key */
void* ecore_tree_get(Ecore_Tree* tree, void* key);
Ecore_Tree_Node* ecore_tree_get_node(Ecore_Tree* tree, void* key);
/* Retrieve the value of node with key greater than or equal to key */
void* ecore_tree_closest_larger_get(Ecore_Tree* tree, void* key);
/* Retrieve the value of node with key less than or equal to key */
void* ecore_tree_closest_smaller_get(Ecore_Tree* tree, void* key);

/* Set the value associated with key to value */
int ecore_tree_set(Ecore_Tree* tree, void* key, void* value);
/* Remove the key from the tree */
int ecore_tree_remove(Ecore_Tree* tree, void* key);

/* Add a node to the tree */
int ecore_tree_node_add(Ecore_Tree* tree, Ecore_Tree_Node* node);
/* Remove a node from the tree */
int ecore_tree_node_remove(Ecore_Tree* tree, Ecore_Tree_Node* node);

/* For each node in the tree perform the for_each_func function */
/* For this one pass in the node */
int ecore_tree_for_each_node(Ecore_Tree* tree, Ecore_For_Each for_each_func,
				 void* user_data);
/* And here pass in the node's value */
int ecore_tree_for_each_node_value(Ecore_Tree* tree,
				   Ecore_For_Each for_each_func,
				   void* user_data);

/* Some basic node functions */
/* Initialize a node */
int ecore_tree_node_init(Ecore_Tree_Node* new_node);
/* Allocate and initialize a new node */
Ecore_Tree_Node* ecore_tree_node_new();
/* Free the desired node */
int ecore_tree_node_destroy(Ecore_Tree_Node* node, 
	   Ecore_Free_Cb free_value, Ecore_Free_Cb free_key);

/* Set the node's key to key */
int ecore_tree_node_key_set(Ecore_Tree_Node* node, void* key);
/* Retrieve the key in node */
void* ecore_tree_node_key_get(Ecore_Tree_Node* node);

/* Set the node's value to value */
int ecore_tree_node_value_set(Ecore_Tree_Node* node, void* value);
/* Retrieve the value in node */
void* ecore_tree_node_value_get(Ecore_Tree_Node* node);

/* Add a function to free the data stored in nodes */
int ecore_tree_free_value_cb_set(Ecore_Tree* tree, Ecore_Free_Cb free_value);
/* Add a function to free the keys stored in nodes */
int ecore_tree_free_key_cb_set(Ecore_Tree* tree, Ecore_Free_Cb free_key);

Ecore_Strbuf* ecore_strbuf_new();
void ecore_strbuf_free(Ecore_Strbuf* buf);
void ecore_strbuf_append(Ecore_Strbuf* buf, char* str);
void ecore_strbuf_append_char(Ecore_Strbuf* buf, char c);
void ecore_strbuf_insert(Ecore_Strbuf* buf, char* str, 
							 size_t pos);
							 
char*  ecore_strbuf_string_get(Ecore_Strbuf* buf);
size_t ecore_strbuf_length_get(Ecore_Strbuf* buf);
int ecore_strbuf_replace(Ecore_Strbuf* buf, char* str, 
							 char* replace_with, uint n);

int ecore_strbuf_replace_all(Ecore_Strbuf* buf, char* str,
								 char* replace_with);

